package com.tedu.api.list;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

/**
 * 数组：遍历数据    遍历数据三种：普通for、增强for、Arrays工具类
 * 【优选】集合：遍历数据    遍历数据三种：普通for、增强for、Iterator迭代器
 * 保存数据优选：集合---遍历数据优选  Iterator
 * Iterator迭代器   接口----依赖Collection提供方法：iterator()
 *
 * 集合：迭代器的使用方法：问、取、删【不是必须操作】
 */
public class Collection_IteratorAPI {
    @Test
    public void testIteratorAPI() {
        Collection c1 = new ArrayList();
        c1.add("one");
        c1.add("tow");
        c1.add("three");
        /**
         * Iterator()方法:获取集合的迭代器---遍历数据
         */
        Iterator it = c1.iterator();
        //迭代器使用：1.问--集合中是否存在元素【集合元素不确定】
        /**
         * hasNext()  返回值：boolean
         * 作用：判断集合中是否还有元素可以遍历，
         * 返回true有元素，false没有元素
         */
        while(it.hasNext()){ // 迭代器：问操作--hasNext()
            //2.取---如果集合中存在元素：取出元素
            /**
             * E next()   返回值：E泛型  简单理解为：Object
             * 作用：遍历取出元素
             */
            String str=(String)it.next();
            System.out.println("集合迭代器："+str);
        }
    }

    /**
     * 集合三种遍历方式：Iterator迭代器【问、取操作】
     * 普通for【难度，需要查API】
     * 增强for【没有难度】
     */
    @Test
    public void testFor() {
        //创建集合
        Collection collection = new ArrayList();
        //需求：添加10个元素，用普通for增加元素：0~9数值
        for (int i=0; i<10;i++){
            collection.add(i);
        }
        System.out.println("打印集合数据：" + collection);
        //获取集合中所有数据----------操作：遍历
        //①使用普通for遍历collection集合，提醒：查API
        //获取数组元素：int[] arr={1,2,3};  数组名[下标]  arr[1]
        //获取集合元素：List---方法          集合名[下标]  ×
        for (int i=0;i<collection.size();i++) {//i 值 拿下标
            System.out.println("普通for输出集合：" + ((List) collection).get(i));
        }

        //②使用增强for遍历：  语法：for(Integer i:集合名)
        //                       for(Object i:collection)
        //collection是顶级集合---可以存任何数据---所以用Object接收
        for (Object i:collection){
            System.out.println("增强for遍历集合:" + i);
        }
    }

    /**
     * 遍历同时对集合做元素删除操作--Iterator迭代器
     * Iterator迭代器--删除操作【真删元素】
     * remove()         返回值：void
     * 作用:删除迭代器获取的元素【理解：next()取元素之后，删除】
     * Iterator迭代器使用规则：问、取、删
     *
     * 作业：使用增强for循环，删除testRemove单元测试中集合包含"元旦"元素
     *       作业单元测试名：testHomeWork()
     *       集合：Iterator 通过迭代--遍历集合--遍历同时删除元素  【推荐】
     *       普通for【不推荐】
     *       增强for【不可以在遍历同时删除元素】
     *       ConcurrentModificationException   并发修改异常
     *       产生原因：增强for底层遍历采用Iterator遍历---迭代器删除元素
     *                                         集合删元素
     *                           增强for中删除集合元素的方法用错
     */
    @Test
    public void testRemove(){
        Collection c=new ArrayList();
        c.add("国庆节");c.add("元旦");c.add("春节");c.add("元宵节");
        //创建集合 Collection--遍历同时删除春节的元素
        System.out.println("Collection集合"+c);
        //1.依赖集合Collection--提供 iteration()方法：创建迭代器对象
        Iterator it=c.iterator();
        //使用迭代器：问、取、删
        while(it.hasNext()){//问：集合中是否有元素
            // 3.获取集合中元素   next() 获取集合中元素，默认类型Object
            String str=(String)it.next();
            //4.删除集合中存在"春节"元素
            //4.1 如果集合中元素名"春节"--删除
            if("春节".equals(str)) {
                it.remove();//删除操作
            }
            //c.remove("春节");  //集合中删除
        }
        System.out.println("迭代器实现删除元素操作:"+c);
    }

    /**
     * 作业：使用增强for循环，删除testRemove单元测试中集合包含"元旦"元素
     *             作业单元测试名：testHomeWork()
     *             集合：Iterator 通过迭代--遍历集合--遍历同时删除元素  【推荐】
     *             普通for【不推荐】
     *             增强for【不可以在遍历同时删除元素】
     *             ConcurrentModificationException   并发修改异常
     *             产生原因：增强for底层遍历采用Iterator遍历---迭代器删除元素
     *                                               集合删元素
     *                                 增强for中删除集合元素的方法用错
     */
    @Test
    public void testHomeWork(){
        Collection<String> c=new ArrayList();
        c.add("国庆节");
        c.add("元旦");
        c.add("春节");
        c.add("元宵节");
        //1.创建Iterator迭代器对象---通过集合获取对象
        Iterator<String> it=c.iterator();
        //2.迭代器遵从问、取、删
        while(it.hasNext()){//问：集合中是否有元素  true
            String str=it.next();//取集合每个元素
            if ("元旦".equals(str)){
                it.remove(); //迭代器it 删除集合元素
                //c.remove(str);  //错误方法 删除肯定报错

            }
        }
//        for (String str:c){
//            if ("元旦".equals(str));{//元旦判断集合中"元旦"
//                c.remove("元旦"); //是集合中元旦，删除
//            }
//            System.out.println("增强for循环："+str);
//        }
        System.out.println("打印集合"+c);
    }
    /**
     * 泛型：与集合搭配使用        E  element元素   理解：Object
     * JDK1.5之后出现泛型，是推出的新特性，集合存任何数据，获取数据非常混乱
     *                  对象、整整、小数型 取 Object 知道类型
     *泛型主要功能是约束集合的类型！
     * 泛型是编译器认可的，JVM虚拟机不认可，认为它是Object对象
     * 使用泛型的好处：1.约束类型，保证数据稳定【统一类型】,获取元素无需造型
     *              2.类型：对象---继承以及继承之后方法使用super
     * 语法： Collection<类型：引用类型、基本类型、包装类型> c=new ArrayList<类型：引用类型、基本类型、包装类型>();
     *                  增强for  (Object i: c)
     */
    @Test
    public void testElement(){
        //JDK1.5   泛型写法
        Collection<String> c1=new ArrayList<String>();
        //JDK1.7   泛型写法          建议使用
        Collection<String> c2=new ArrayList<>();
        c2.add("老刘");c2.add("老祁");c2.add("牢大");
        Iterator<String> it=c2.iterator();
        while (it.hasNext()) {//问是否存在数据，存在true
            String str=it.next();
        }
        //c2.add(new Object());
        Collection<Integer> c3=new ArrayList<>();
        //Collection<Boolean> c4=new ArrayList<Boolean>();

        //泛型定义：?代表：不限制类型【没有意义--null】   项目非常大--功能
        Collection<?> c4=new ArrayList<>();
        //c4.add("字符串");c4.add(1);c4.add(1.123);c4.add(new Object());
        c4.add(null);//只能存没有意义的值：引用值：引用类型--默认值：null
    }
    /**
     * 泛型中通配符  ?【任意类型】  的使用
     * ?【任意类型】  extends  父类
     * 【任意类型：父类的所有子类】   --约束--
     */
    @Test
    public void testE(){
        //测试：  创建父类：Fruit--属性：name名字 | 方法：获取名称
        //       创建两个子类：Apple、Orange--构造器：传水果名
        //       创建类TestJob类  泛型 ? extends 父类
        //约束----静态的方法 printFruit
        //约束只能是继承父类的子类才可以使用
        //单元测试：：testE中测试--约束是否限制成功
        //实际开发应用中，高级程序员指定！
        Collection<Apple> apples=new ArrayList<>();
        apples.add(new Apple());//存入Apple对象
        TestJob.printFruit(apples);//上界限定操作：针对集合
        Collection<Orange> oranges=new ArrayList<>();
        oranges.add(new Orange());
        TestJob.printFruit(oranges);
        Collection<Pear> pears=new ArrayList<>();
        pears.add(new Pear());
        //TestJob.printFruit(pears);//上界限定操作：针对集合
    }
    @Test
    public void testHomeWork2() {
        Collection<String> c = new ArrayList<>();
        c.add("国庆节");
        c.add("元旦");
        c.add("春节");
        c.add("元宵节");

        boolean removed = false; // 标记是否已删除"元旦"

        // 使用增强for循环遍历集合
        for (String str : c.toArray(new String[0])) { // 使用toArray避免ConcurrentModificationException
            if ("元旦".equals(str)) {
                // 注意：这里不能直接使用c.remove(str)，因为会抛出ConcurrentModificationException
                // 但由于我们使用了toArray，这里实际上是在遍历一个数组副本，所以不能直接修改原集合
                // 因此，我们需要一个额外的步骤来从原集合中删除元素
                if (!removed) { // 确保只删除一次
                    c.remove("元旦"); // 在循环外部进行删除操作
                    removed = true; // 标记为已删除
                }
            }
            // 注意：这里的打印操作是在数组副本上进行的，所以不会反映原集合的更改
        }

        // 由于上面的循环实际上是在数组副本上进行的，我们需要再次遍历原集合来打印元素
        for (String str : c) {
            System.out.println("增强for循环（实际遍历原集合）：" + str);
        }

        System.out.println("打印集合：" + c);
    }
}

//  集合重点